using System;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{
    public class RequiredStringRuleTest
    {


        const string expectedErrorMessage = "expectedErrorMessage";
        const string expectedRuleSet = "EXPECTEDRULESET";
        const string expectedInitialValue = "a";

        
        [TestFixture]
        public class Construction
        {
            [Test]
            public void Simple1()
            {
                var rule = new RequiredStringRule(expectedErrorMessage, false, true);
                Assert.IsFalse(rule.HasInitialValue);
                Assert.AreEqual(expectedErrorMessage, rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsNull(rule.IgnoreCase);
            }


            [Test]
            public void Simple2()
            {
                var rule = new RequiredStringRule(expectedErrorMessage, false, expectedInitialValue, true, true);
                Assert.IsTrue(rule.HasInitialValue);
                Assert.AreEqual(expectedErrorMessage, rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
                Assert.AreEqual(expectedInitialValue, rule.InitialValue);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsTrue(rule.IgnoreCase.Value);
            }


            [Test]
            [ExpectedException(typeof(NullReferenceException))]
            public void ExceptionInitialValueNull1()
            {
                new RequiredStringRule(expectedErrorMessage, false, null, true, true);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: initialValue")]
            public void ExceptionInitialValueEmpty1()
            {
               new RequiredStringRule(expectedErrorMessage, false, string.Empty, true, true);
            }


            [Test]
            public void Simple3()
            {
                var rule = new RequiredStringRule(expectedErrorMessage);
                Assert.IsFalse(rule.HasInitialValue);
                Assert.AreEqual(expectedErrorMessage, rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsNull(rule.IgnoreCase);
            }


            [Test]
            public void Simple4()
            {
                var rule = new RequiredStringRule();
                Assert.IsFalse(rule.HasInitialValue);
                Assert.IsNull(rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsNull(rule.IgnoreCase);
            }

        }
        [TestFixture]
        public class IsEquivalent
        {


            [Test]
            public void Simple()
            {
                var rule1 = new RequiredStringRule(null, false, "a", true, true);
                var rule2 = new RequiredStringRule(null, false, "a", true, true);
                Assert.IsTrue(rule1.IsEquivalent(rule2));


                rule1 = new RequiredStringRule(null, false, "a", true, true);
                rule2 = new RequiredStringRule(null, false, "a", true, false);
                Assert.IsFalse(rule1.IsEquivalent(rule2));

                rule1 = new RequiredStringRule(null, false, "a", true, true);
                rule2 = new RequiredStringRule(null, false, "a", false, true);
                Assert.IsFalse(rule1.IsEquivalent(rule2));

                rule1 = new RequiredStringRule(null, false, "a", true, true);
                rule2 = new RequiredStringRule(null, false, " a ", true, true);
                Assert.IsTrue(rule1.IsEquivalent(rule2));

                rule1 = new RequiredStringRule(null, false, "a", true, true);
                rule2 = new RequiredStringRule(null, false, "b", true, true);
                Assert.IsFalse(rule1.IsEquivalent(rule2));

            }
        }
        [TestFixture]
        public class Validate
        {
            [Test]
            public void NoInitialValueTrimSpacesIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, true);

                Assert.IsNotNull(rule.Validate(null, null, null, null));
                Assert.IsNotNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNotNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, " A ", null, null));

            }
            [Test]
            public void InitialValueTrimSpacesIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, " a ", true, true);

                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNotNull(rule.Validate(null, "a", null, null));
                Assert.IsNotNull(rule.Validate(null, "\t a ", null, null));
                Assert.IsNotNull(rule.Validate(null, "A", null, null));
                Assert.IsNotNull(rule.Validate(null, "\t A ", null, null));

            }

            [Test]
            public void InitialValueNoTrimSpacesIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, "a", false, true);

                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNotNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, "\t a ", null, null));
                Assert.IsNotNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, "\t A ", null, null));

            }
            [Test]
            public void InitialValueTrimSpacesNoIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, "a", true, false);

                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNotNull(rule.Validate(null, "a", null, null));
                Assert.IsNotNull(rule.Validate(null, "\t a ", null, null));
                Assert.IsNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, "\t A ", null, null));

            }

            [Test]
            public void InitialValueNoTrimSpacesNoIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, "a", false, false);

                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNotNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, " a ", null, null));
                Assert.IsNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, " A ", null, null));

            }
            [Test]
            public void NoInitialValueNoTrimSpacesNoIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, false);

                Assert.IsNotNull(rule.Validate(null, null, null, null));
                Assert.IsNotNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, " a ", null, null));
                Assert.IsNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, " A ", null, null));
            }

            [Test]
            public void NoInitialValueTrimSpacesNoIgnoreCase()
            {
                var rule = new RequiredStringRule(null, false, true);

                Assert.IsNotNull(rule.Validate(null, null, null, null));
                Assert.IsNotNull(rule.Validate(null, string.Empty, null, null));
                Assert.IsNotNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "s", null, null));
                Assert.IsNull(rule.Validate(null, " s ", null, null));
                Assert.IsNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, " a ", null, null));
                Assert.IsNull(rule.Validate(null, "A", null, null));
                Assert.IsNull(rule.Validate(null, " A ", null, null));

            }
        }
        [TestFixture]
        public class RuleInterpretation
        {

            [Test]
            public void Simple1()
            {

                var rule = new RequiredStringRule(null, false, true);
                Assert.IsNotNull(rule.RuleInterpretation);

            }
            [Test]
            public void Simple2()
            {

                var rule = new RequiredStringRule(null, false, false);
                Assert.IsNotNull(rule.RuleInterpretation);

            }
            [Test]
            public void Simple3()
            {
                var rule = new RequiredStringRule(null, false, "initialValue", true, true);
                Assert.IsNotNull(rule.RuleInterpretation);
            }

        }
        [TestFixture]
        public class CheckTypes
        {
            [Test]
            public void Simple()
            {
                var rule = new RequiredStringRule(null, false, true);
                rule.CheckType(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.RequiredStringRule. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionInvalidType()
            {
                var rule = new RequiredStringRule(null, false, true);
                        rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
        }
    }
}